package com.exigen.performance.test.webapp.services.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;

import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;

import com.exigen.performance.test.webapp.dao.ConfigurationDao;
import com.exigen.performance.test.webapp.dao.ProjectDao;
import com.exigen.performance.test.webapp.dao.RequestTemplateDao;
import com.exigen.performance.test.webapp.dao.ScenarioDao;
import com.exigen.performance.test.webapp.dao.ScenarioTypeDao;

import com.exigen.performance.test.webapp.dao.TransactionDao;
import com.exigen.performance.test.webapp.domain.ConfigurationEntity;
import com.exigen.performance.test.webapp.domain.ProjectEntity;
import com.exigen.performance.test.webapp.domain.ReportEntity;
import com.exigen.performance.test.webapp.domain.RequestTemplateEntity;
import com.exigen.performance.test.webapp.domain.ScenarioEntity;
import com.exigen.performance.test.webapp.domain.ScenarioTypeEntity;
import com.exigen.performance.test.webapp.domain.TestSummaryEntity;
import com.exigen.performance.test.webapp.domain.TransactionEntity;
import com.exigen.performance.test.webapp.services.ReportServices;
import com.exigen.performance.test.webapp.dao.TestSummaryDao;

/**
 * Class that collect test data from data access objects and fills report
 * templates.
 * 
 * @author Maksim Savchuk
 * 
 */
/**
 * @author Maksim Savchuk
 * 
 */
public class ReportServicesImpl implements ReportServices {

	// Average response report template location.
	private final String avgResponse = "";
	private final String responseTime = "/reports/response_time.jasper";
	private final String responseSize = "/reports/response_size.jasper";
	private final String hits = "/reports/hits.jasper";
	private final String throughput = "/reports/throughput.jasper";
	private final String historical = "/reports/historical.jasper";
	private final String historicalAvg = "/reports/historical_avg.jasper";

	// DAO classes;
	ProjectDao projectDao;
	TestSummaryDao testSummaryDao;
	ScenarioDao scenarioDao;
	ScenarioTypeDao scenarioTypeDao;
	TransactionDao transactionDao;
	RequestTemplateDao requestTemplateDao;
	ConfigurationDao configurationDao;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.exigen.performance.test.webapp.services.ReportServices#generateReport
	 * (com.exigen.performance.test.webapp.domain.ReportEntity)
	 */
	public JasperPrint generateReport(ReportEntity report) throws Exception {
		File reportFile;
		if (report.isIntermediate()) {
			// Intermediate report
			Map<String, Object> parameters;
			List<TestSummaryEntity> testSummary = this
					.getTestSummaryByReportEntity(report);
			// Create map of parameters for report
			parameters = new HashMap<String, Object>();
			List<Long> transactionIdList = new ArrayList<Long>();
			// Since intermediate report support only one test summary we will
			// use id of first passed TestSummaryEntity.
			Long testSummaryId = testSummary.get(0).getId();
			for (int i = 0; i < report.getTransactions().size(); i++) {
				transactionIdList.add(report.getTransactions().get(i).getId());
			}
			switch (report.getType()) {
			case 1:// Response time report

				reportFile = new File(
						((ServletContext) FacesContext.getCurrentInstance()
								.getExternalContext().getContext())
								.getRealPath(responseTime));

				if (reportFile.exists()) {

					parameters.put("TESTSUMMARY", testSummaryId);
					parameters.put("TRANSACTION", transactionIdList);
					// Filling report
					JasperPrint jasperPrint = JasperFillManager.fillReport(
							reportFile.getAbsolutePath(), parameters,
							testSummaryDao.getConnection());
					return jasperPrint;

				} else {
					throw new JRRuntimeException("Report file not found!");
				}

			case 2: // Throughput report
				reportFile = new File(
						((ServletContext) FacesContext.getCurrentInstance()
								.getExternalContext().getContext())
								.getRealPath(throughput));

				if (reportFile.exists()) {
					// Requesting time interval configuration for throughput.
					ConfigurationEntity config = configurationDao
							.getConfigurationByName("THROUGHPUT_INTERVAL");
					int interval;
					try {
						interval = Integer.parseInt(config.getValue());
					} catch (Exception e) {
						throw new Exception("Configuration error!");
					}
					parameters.put("TESTSUMMARY", testSummaryId);
					// Since throughput report supports only one transaction we
					// will
					// use id of first passed TransactionEntity.
					parameters.put("TRANSACTION", transactionIdList.get(0));
					parameters.put("INTERVAL", interval);
					// Filling report
					JasperPrint jasperPrint = JasperFillManager.fillReport(
							reportFile.getAbsolutePath(), parameters,
							testSummaryDao.getConnection());
					return jasperPrint;

				} else {
					throw new JRRuntimeException("Report file not found!");
				}
			case 3:// Response size report
				reportFile = new File(
						((ServletContext) FacesContext.getCurrentInstance()
								.getExternalContext().getContext())
								.getRealPath(responseSize));

				if (reportFile.exists()) {
					parameters.put("TESTSUMMARY", testSummaryId);
					parameters.put("TRANSACTION", transactionIdList);
					// Filling report
					JasperPrint jasperPrint = JasperFillManager.fillReport(
							reportFile.getAbsolutePath(), parameters,
							testSummaryDao.getConnection());
					return jasperPrint;

				} else {
					throw new JRRuntimeException("Report file not found!");

				}

			case 4:// Hits count report
				reportFile = new File(
						((ServletContext) FacesContext.getCurrentInstance()
								.getExternalContext().getContext())
								.getRealPath(hits));

				if (reportFile.exists()) {

					ConfigurationEntity config = configurationDao
							.getConfigurationByName("HITS_INTERVAL");
					int interval;
					try {
						interval = Integer.parseInt(config.getValue());
					} catch (Exception e) {
						throw new Exception("Configuration error!");
					}

					parameters.put("TESTSUMMARY", testSummaryId);
					// Since hit count report supports only one transaction we
					// will use id of first passed TransactionEntity.
					parameters.put("TRANSACTION", transactionIdList.get(0));
					parameters.put("INTERVAL", interval);
					// Filling report
					JasperPrint jasperPrint = JasperFillManager.fillReport(
							reportFile.getAbsolutePath(), parameters,
							testSummaryDao.getConnection());
					return jasperPrint;

				} else {
					throw new JRRuntimeException("Report file not found!");
				}

			}
		} else {
			// Historical report
			if (report.getType() == 0) {
				reportFile = new File(
						((ServletContext) FacesContext.getCurrentInstance()
								.getExternalContext().getContext())
								.getRealPath(historical));
			} else {
				reportFile = new File(
						((ServletContext) FacesContext.getCurrentInstance()
								.getExternalContext().getContext())
								.getRealPath(historicalAvg));
			}

			if (reportFile.exists()) {
				List<TestSummaryEntity> testSummary;
				if (report.isTemplate()) {

					// If report requested as a template additional operations
					// required
					testSummary = testSummaryDao
							.getRelatedTestSummaryIdInTimeInterval(report);
					if (testSummary.size() == 0)
						throw new Exception(
								"No requested tests in current time interval!");
				} else {
					// Check if in selected time interval is test data;
					testSummary = report.getTestSummaries();
				}
				// Create map of parameters for report
				Map<String, Object> parameters = new HashMap<String, Object>();
				List<Long> transactionIdList = new ArrayList<Long>();
				List<Long> testSummaryIdList = new ArrayList<Long>();
				for (int i = 0; i < testSummary.size(); i++) {
					testSummaryIdList.add(testSummary.get(i).getId());
				}
				for (int i = 0; i < report.getTransactions().size(); i++) {
					transactionIdList.add(report.getTransactions().get(i)
							.getId());
				}
				parameters.put("TESTSUMMARY", testSummaryIdList);
				parameters.put("TRANSACTIONS", transactionIdList);
				// Filling report
				JasperPrint jasperPrint = JasperFillManager.fillReport(
						reportFile.getAbsolutePath(), parameters,
						testSummaryDao.getConnection());
				return jasperPrint;

			} else {
				throw new JRRuntimeException("Report file not found!");
			}
		}
		return null;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.exigen.performance.test.webapp.services.ReportServices#getProjectList
	 * ()
	 */
	public List<ProjectEntity> getProjectList() {
		return projectDao.findAll();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.exigen.performance.test.webapp.services.ReportServices#
	 * getTestSummaryByReportEntity
	 * (com.exigen.performance.test.webapp.domain.ReportEntity)
	 */
	public List<TestSummaryEntity> getTestSummaryByReportEntity(
			ReportEntity report) {
		return testSummaryDao.getTestSummaryByReportEntity(report);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.exigen.performance.test.webapp.services.ReportServices#
	 * getScenariosByProject(java.lang.Long)
	 */
	public List<ScenarioEntity> getScenariosByProject(Long projectId) {
		return scenarioDao.getScenarioByProject(projectId);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.exigen.performance.test.webapp.services.ReportServices#getScenarioType
	 * (java.lang.Long, java.lang.Long)
	 */
	public List<ScenarioTypeEntity> getScenarioType(Long projectId,
			Long scenarioId) {
		return scenarioTypeDao.getScenatioType(projectId, scenarioId);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.exigen.performance.test.webapp.services.ReportServices#getBranchIdList
	 * (java.lang.Long, java.lang.Long, java.util.List)
	 */

	public List<String> getBranchIdList(Long projectId, Long scenarioId,
			List<Long> scenarioTypeId) {
		return testSummaryDao.getBranchIdListByProjectData(projectId,
				scenarioId, scenarioTypeId);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.exigen.performance.test.webapp.services.ReportServices#getBuildIdList
	 * (java.lang.Long, java.lang.Long, java.util.List, java.util.List)
	 */
	public List<String> getBuildIdList(Long projectId, Long scenarioId,
			List<Long> scenarioTypeId, List<String> branchId) {

		return testSummaryDao.getBuildIdListByProjectData(projectId,
				scenarioId, scenarioTypeId, branchId);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.exigen.performance.test.webapp.services.ReportServices#getStateList
	 * (java.lang.Long, java.lang.Long, java.util.List, java.util.List,
	 * java.util.List)
	 */
	public List<String> getStateList(Long projectId, Long scenarioId,
			List<Long> scenarioTypeId, List<String> branchId,
			List<String> buildId) {

		return testSummaryDao.getStateListByProjectData(projectId, scenarioId,
				scenarioTypeId, branchId, buildId);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.exigen.performance.test.webapp.services.ReportServices#
	 * gaetTransactionList(java.lang.Long, java.lang.Long, java.util.List,
	 * java.util.List, java.util.List, java.util.List)
	 */
	public List<TransactionEntity> getTransactionList(ReportEntity report) {
		List<TestSummaryEntity> summaries = report.getTestSummaries();
		List<Long> testSummaryId = new ArrayList<Long>();
		for (int i = 0; i < summaries.size(); i++) {
			testSummaryId.add(summaries.get(i).getId());
		}
		return transactionDao.getTransactionList(testSummaryId);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.exigen.performance.test.webapp.services.ReportServices#createNewTemplate
	 * (com.exigen.performance.test.webapp.domain.RequestTemplateEntity)
	 */
	public void createNewTemplate(RequestTemplateEntity template) {
		requestTemplateDao.save(template);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.exigen.performance.test.webapp.services.ReportServices#
	 * getAllRequestTemplates()
	 */
	public List<RequestTemplateEntity> getAllRequestTemplates() {
		return requestTemplateDao.findAll();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.exigen.performance.test.webapp.services.ReportServices#getConfiguration
	 * (java.lang.String)
	 */
	public String getConfiguration(String configurationName) {
		return (configurationDao.getConfigurationByName(configurationName))
				.getValue();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.exigen.performance.test.webapp.services.ReportServices#deleteTemplate
	 * (com.exigen.performance.test.webapp.domain.RequestTemplateEntity)
	 */
	public void deleteTemplate(RequestTemplateEntity template) {
		requestTemplateDao.delete(template);
	}

	// Getters and setters
	public ProjectDao getProjectDao() {
		return projectDao;
	}

	public void setProjectDao(ProjectDao projectDao) {
		this.projectDao = projectDao;
	}

	public TestSummaryDao getTestSummaryDao() {
		return testSummaryDao;
	}

	/**
	 * @param testSummaryDao
	 */
	public void setTestSummaryDao(TestSummaryDao testSummaryDao) {
		this.testSummaryDao = testSummaryDao;
	}

	public ScenarioDao getScenarioDao() {
		return scenarioDao;
	}

	public void setScenarioDao(ScenarioDao scenarioDao) {
		this.scenarioDao = scenarioDao;
	}

	public ScenarioTypeDao getScenarioTypeDao() {
		return scenarioTypeDao;
	}

	public void setScenarioTypeDao(ScenarioTypeDao scenarioTypeDao) {
		this.scenarioTypeDao = scenarioTypeDao;
	}

	public TransactionDao getTransactionDao() {
		return transactionDao;
	}

	public void setTransactionDao(TransactionDao transactionDao) {
		this.transactionDao = transactionDao;
	}

	public ConfigurationDao getConfigurationDao() {
		return configurationDao;
	}

	public void setConfigurationDao(ConfigurationDao configurationDao) {
		this.configurationDao = configurationDao;
	}

	public String getAvgResponse() {
		return avgResponse;
	}

	public String getResponseTime() {
		return responseTime;
	}

	public String getResponseSize() {
		return responseSize;
	}

	public String getHits() {
		return hits;
	}

	public RequestTemplateDao getRequestTemplateDao() {
		return requestTemplateDao;
	}

	public void setRequestTemplateDao(RequestTemplateDao requestTemplateDao) {
		this.requestTemplateDao = requestTemplateDao;
	}

	public String getHistorical() {
		return historical;
	}

	public String getHistoricalAvg() {
		return historicalAvg;
	}

}
